package chart;

import java.awt.Graphics2D;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ArrayUtils;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.MovingAverage;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.DefaultHighLowDataset;
import org.jfree.data.xy.IntervalXYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
import org.jfree.util.ArrayUtilities;

import util.Candle;
import util.Util;

public class SgxChart extends ApplicationFrame {

	private DefaultHighLowDataset priceData;
	private TimeSeriesCollection smaData;
	private TimeSeriesCollection emaData;
	private TimeSeriesCollection volumeData;
	private TimeSeriesCollection volumeMAData;
	private double maxVolume;

	public SgxChart(String path, String stockName) {
	  super(stockName);
	
	 createDataset(path, stockName);
	  final JFreeChart chart = createChart(priceData);
	  XYPlot plot = (XYPlot) chart.getPlot();
	  
	  NumberAxis priceAxis = (NumberAxis) plot.getRangeAxis(0);
	  priceAxis.setAutoRangeIncludesZero(false);
	  priceAxis.setUpperBound(3);
	  priceAxis.setLowerBound(1.5);

	  NumberAxis volumeAxis = new NumberAxis("Volume");
	  volumeAxis.setAutoRangeIncludesZero(false);
	  volumeAxis.setUpperBound(2 * maxVolume);
	  plot.setRangeAxis(1, volumeAxis);
	  
	  plot.setDataset(1, smaData);
	  plot.setDataset(2, emaData);
	  plot.setDataset(3, volumeData);
	  plot.setDataset(4, volumeMAData);

	  XYLineAndShapeRenderer smaRenderer = new XYLineAndShapeRenderer(true, false);
	  plot.mapDatasetToRangeAxis(1, 0);

	  XYLineAndShapeRenderer emaRenderer = new XYLineAndShapeRenderer(true, false);
	  plot.mapDatasetToRangeAxis(2, 0);

	  XYBarRenderer volumeRenderer = new XYBarRenderer(0.4);
	  volumeRenderer.setShadowXOffset(0);
	  volumeRenderer.setShadowYOffset(0);
	  volumeRenderer.setDrawBarOutline(false);
	  volumeRenderer.setDrawBarOutline(false);
      // flat bars look best...
	  volumeRenderer.setBarPainter(new StandardXYBarPainter());
	  volumeRenderer.setShadowVisible(false);
      plot.mapDatasetToRangeAxis(3, 1);
	
	  XYLineAndShapeRenderer volumeMARenderer = new XYLineAndShapeRenderer(true, false);
	  plot.mapDatasetToRangeAxis(4, 1);
	  
  	  plot.setRenderer(1, smaRenderer);
  	  plot.setRenderer(2, emaRenderer);
  	  plot.setRenderer(3, volumeRenderer);
  	  plot.setRenderer(4, volumeMARenderer);
      	  
	  final ChartPanel chartPanel = new ChartPanel(chart);
	  chartPanel.setPreferredSize(new java.awt.Dimension(600, 350));
	  setContentPane(chartPanel);
  }

 private void createDataset(String path, String stockName) {

	 try {
		 File folder = new File(path);
		 if (!folder.isDirectory()) return;
		 String[] filenames = folder.list();

		DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); 
		String line;
		ArrayList<Date> dateList = new ArrayList<Date>();
		ArrayList<Double> priceOpenList = new ArrayList<Double>();
		ArrayList<Double> priceHighList = new ArrayList<Double>();
		ArrayList<Double> priceLowList = new ArrayList<Double>();
		ArrayList<Double> priceCloseList = new ArrayList<Double>();
		ArrayList<Double> volumeList = new ArrayList<Double>();
		
		  TimeSeries priceCloseSeries = new TimeSeries("Price Closed");
		  TimeSeries volumeSeries = new TimeSeries("Volume");
			  
		 for (int i = 0; i < filenames.length; i++) {
			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path + filenames[i]),"UTF-8"));
			br.readLine();

			while ((line = br.readLine()) != null) {
				if (!line.contains(stockName)) continue;
				System.out.println(line);
				StringTokenizer st = new StringTokenizer(line, ";");
				Date date = df.parse(st.nextToken());
				st.nextToken();
				st.nextToken();
				st.nextToken();
				double priceHigh = Double.parseDouble(st.nextToken());
				double priceLow = Double.parseDouble(st.nextToken());
				double priceClose = Double.parseDouble(st.nextToken());
				double priceChanged = Double.parseDouble(st.nextToken());
				int volume = Integer.parseInt(st.nextToken());
				st.nextToken();
				st.nextToken();
				st.nextToken();
				double priceOpen = Double.parseDouble(st.nextToken());
				
				dateList.add(date);
				priceOpenList.add(priceOpen);
				priceHighList.add(priceHigh);
				priceLowList.add(priceLow);
				priceCloseList.add(priceClose);
				volumeList.add((double) volume);
				priceCloseSeries.add(new Day(date), priceClose);
				volumeSeries.add(new Day(date), volume);
				  maxVolume = Math.max(maxVolume, volume);
			}
		 }
		 
		Date[] date = dateList.toArray(new Date[dateList.size()]);
		Double[] high = priceHighList.toArray(new Double[priceHighList.size()]);
		Double[] low = priceLowList.toArray(new Double[priceLowList.size()]);
		Double[] open = priceOpenList.toArray(new Double[priceOpenList.size()]);
		Double[] close = priceCloseList.toArray(new Double[priceCloseList.size()]);
		Double[] volume = volumeList.toArray(new Double[volumeList.size()]);
		
		double[] high_ = ArrayUtils.toPrimitive(high); 
		double[] low_ = ArrayUtils.toPrimitive(low); 
		double[] open_ = ArrayUtils.toPrimitive(open); 
		double[] close_ = ArrayUtils.toPrimitive(close); 
		double[] volume_ = ArrayUtils.toPrimitive(volume); 

		  TimeSeries emaSeries = new TimeSeries("EMA");
		  for (int i = 0; i < close_.length; i++) {
			  try {
				  Date d = date[i];
				  double ema = Util.getEMA(30, close_, i);
				  emaSeries.add(new Day(d), ema);
			  }
			  catch (Exception e) {
				  
			  }
		  }
		  emaData = new TimeSeriesCollection(emaSeries);
		  
		  priceData = new DefaultHighLowDataset("", date, high_, low_, open_, close_, volume_);
		  TimeSeriesCollection priceCloseData = new TimeSeriesCollection(priceCloseSeries);
		  smaData = MovingAverage.createMovingAverage(priceCloseData, "SMA", 10, 10);
		  volumeData = new TimeSeriesCollection(volumeSeries);
		  volumeMAData = MovingAverage.createMovingAverage(volumeData, "MA", 14, 14);
	 }
	 catch (Exception e) {
		 e.printStackTrace();
	 }
  }

 private JFreeChart createChart(final DefaultHighLowDataset dataset) {
  final JFreeChart chart = ChartFactory.createCandlestickChart("Candlestick Demo", "Time", "Price", dataset, false);
  return chart;
  }

 public static void main(String args[]) {
	 SgxChart chart = new SgxChart(args[0], "ASCENDAS REAL ESTATE INV TRUST");
	  chart.pack();
	  RefineryUtilities.centerFrameOnScreen(chart);
	  chart.setVisible(true);
  }
}